#include "stdafx.h"
#include "VertexBuffer.h"

#include "../render/RenderDevice.h"

namespace WindGE
{
	VertexBuffer::VertexBuffer()
		: render_device_(nullptr)
		, vb_type_(evb_vertex)
		, isdynamic_(false)
		, stride_(0)
		, count_(0)
		, d3d_buffer_(nullptr)
	{
	}

	VertexBuffer::~VertexBuffer()
	{
		safe_release(d3d_buffer_);
	}

	bool VertexBuffer::init(RenderDevicePtr renderDevice, EVBType type, bool isDynamic)
	{
		render_device_ = renderDevice;
		vb_type_ = type;
		isdynamic_ = isDynamic;
		
		buffer_desc_.Usage			= isDynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_IMMUTABLE;
		buffer_desc_.CPUAccessFlags = isDynamic ? D3D11_CPU_ACCESS_WRITE : 0;

		if (vb_type_ == evb_vertex)		buffer_desc_.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		else if (vb_type_ == evb_index) buffer_desc_.BindFlags = D3D11_BIND_INDEX_BUFFER;

		buffer_desc_.MiscFlags = 0;
		buffer_desc_.StructureByteStride = 0;

		return true;
	}

	bool VertexBuffer::build(const void* datas, unsigned int stride, unsigned int count)
	{
		stride_ = stride;
		count_ = count;

		buffer_desc_.ByteWidth = stride_ * count_;

		D3D11_SUBRESOURCE_DATA vinitData;
		vinitData.pSysMem = datas;
		vinitData.SysMemPitch = 0;
		vinitData.SysMemSlicePitch = 0;

		HRESULT hr = render_device_->device()->CreateBuffer(&buffer_desc_, &vinitData, &d3d_buffer_);
		if (FAILED(hr)) return false;

		return true;
	}

	void VertexBuffer::bind_vertex(unsigned int slot, unsigned int offset)
	{
		if (vb_type_ == evb_index) return;

		render_device_->device_context()->IASetVertexBuffers(slot, 1, &d3d_buffer_, &stride_, &offset);
	}

	void VertexBuffer::bind_index(unsigned int offset)
	{
		if (vb_type_ == evb_vertex) return;

		render_device_->device_context()->IASetIndexBuffer(d3d_buffer_, DXGI_FORMAT_R32_UINT, offset);
	}

	bool VertexBuffer::map(void** dataPtr, unsigned int mapType)
	{
		if (!isdynamic_)
		{
			*dataPtr = nullptr;
			return false;
		}

		HRESULT hr = render_device_->device_context()->Map(d3d_buffer_, 0, (D3D11_MAP)mapType, 0, &mapped_resource_);
		if (FAILED(hr))
		{
			*dataPtr = nullptr;
			return false;
		}
		
		*dataPtr = mapped_resource_.pData;

		return true;
	}

	bool VertexBuffer::unmap()
	{
		if (!isdynamic_) return false;

		render_device_->device_context()->Unmap(d3d_buffer_, 0);

		return true;
	}

}//end namespace WindGE

